package run

import (
	"encoding/json"
	"fmt"
	"go-redis/utils"
	"io"
	"net/http"
)

type Cmd struct {
	Op   string
	Data KV
	// Response *http.ResponseWriter
}

var queue = make(chan Cmd)
var ReponseQueue = make(chan string)

type Server struct {
	Port     int
	Address  string
	Server   *http.Server
	Database *Database
}
type Handler interface {
	ServeHTTP(http.ResponseWriter, *http.Request)
}

type KV struct {
	Key string `json:"key"`
	Val string `json:"val"`
}

func NewServer(port int, address string) (*Server, error) {
	server := &Server{
		Port:    port,
		Address: address,
		Server: &http.Server{
			Addr:    address,
			Handler: nil,
		},
		Database: NewDataBase(),
	}
	go func() {
		for {
			cmd := <-queue
			switch cmd.Op {
			case "get":
				if val := server.Database.Get(cmd.Data.Key); val != nil {
					ReponseQueue <- val.Val.(string)
				} else {
					ReponseQueue <- "nil"
				}
			case "set":
				if ok := server.Database.Set(cmd.Data.Key, cmd.Data.Val); ok {
					ReponseQueue <- "ok"

				} else {
					ReponseQueue <- "error"
				}

			}
		}
	}()
	return server, nil
}

func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	var err error
	var body []byte
	var data KV
	if body, err = io.ReadAll(req.Body); err != nil {
		w.WriteHeader(http.StatusBadRequest)
		utils.Log.Error(fmt.Sprintf("error: %s", err.Error()))
	}
	if err = json.Unmarshal(body, &data); err != nil {
		w.WriteHeader(http.StatusBadRequest)
		utils.Log.Error(fmt.Sprintf("error: %s", err.Error()))
	}
	switch req.URL.Path {
	case "/get":
		utils.Log.Debug("get key " + data.Key + " " + data.Val)
		queue <- Cmd{Op: "get", Data: data}
		w.Write([]byte(<-ReponseQueue))
	case "/set":
		utils.Log.Debug("set key" + data.Key + "value" + data.Val)
		queue <- Cmd{Op: "set", Data: data}
		w.Write([]byte(<-ReponseQueue))
	}

}
